﻿using Xejen.Ipc.Framework.Flows;
using Xejen.Ipc.Framework.Steps;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Xejen.Ipc.Framework.Controllers
{
    /// <inheritdoc cref="IController{TData}"/>
    internal abstract class Controller<TData> : IController<TData>
        where TData : new()
    {
        /// <summary>
        /// 日志
        /// </summary>
        protected ILogger Logger;
        /// <summary>
        /// 下一个控制器
        /// </summary>
        protected IController<TData> Next;

        /// <inheritdoc/>
        public string Name => this.GetType().Name.Split('`')[0] + "控制器";
        /// <inheritdoc/>
        public IReadOnlyList<IStep<TData>> Steps => _steps.AsReadOnly();

        /// <summary>
        /// 步骤列表
        /// </summary>
        private readonly List<IStep<TData>> _steps = new List<IStep<TData>>();

        /// <inheritdoc/>
        public event EventHandler<ControllerEventArgs<TData>> Started;
        /// <inheritdoc/>
        public event EventHandler<ControllerEventArgs<TData>> Completed;
        /// <inheritdoc/>
        public event EventHandler<ErrorEventArgs<TData>> Error;

        /// <inheritdoc cref="Controller{TData}"/>
        /// <param name="steps">步骤列表</param>
        protected Controller(params IStep<TData>[] steps)
        {
            Check.NotNull(steps, nameof(steps));

            Logger = HostRuntime.LoggerManager.CreateLogger<Controller<TData>>();

            steps.ForEach((step) =>
            {
                step.Error += (sender, args) =>
                {
                    OnError(this, args);
                };
            });

            _steps.AddRange(steps);
        }

        /// <summary>
        /// 设置下一个控制器
        /// </summary>
        /// <param name="next"><inheritdoc cref="Next" path="/summary"/></param>
        public void SetNext(IController<TData> next)
        {
            Next = next;
        }

        /// <inheritdoc/>
        public virtual async Task RunAsync(IFlowExecutionContext<TData> context, CancellationToken cancellationToken = default)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                Debug.WriteLine($"控制器内的当前流程状态被取消，流程停止并返回");
                return;
            }
            if (context.Flow.Status == FlowStatus.Stopped)
            {
                Debug.WriteLine($"控制器内的当前流程状态变更为：{context.Flow.Status}，流程停止并返回");
                return;
            }
            while (context.Flow.Status == FlowStatus.Paused)
            {
                await Task.Delay(10);
                continue;
            }

            if (Next != null)
            {
                await Next.RunAsync(context, cancellationToken);
            }
        }

        /// <summary>
        /// 当控制器进入时触发
        /// </summary>
        protected virtual void OnStarted(object sender, ControllerEventArgs<TData> args)
        {
            Started?.Invoke(sender, args);
        }
        /// <summary>
        /// 当控制器出去时触发
        /// </summary>
        protected virtual void OnCompleted(object sender, ControllerEventArgs<TData> args)
        {
            Completed?.Invoke(sender, args);
        }
        /// <summary>
        /// 当发生错误时触发
        /// </summary>
        protected virtual void OnError(object sender, ErrorEventArgs<TData> args)
        {
            Logger.LogError(args.Exception, args.Exception.Message);
            Error?.Invoke(sender, args);
        }
    }
}
